home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1999 June: Reference Library / Dev.CD Jun 99 RL Disk 1.toast / Technical Documentation / Macintosh Technotes and Q&As / technotes / tn / tn_1080.cw < prev    next >
Encoding:
Text File  |  1998-04-27  |  59.3 KB  |  1,009 lines  |  [TEXT/R*ch]

  1. ˜BOBOÁô¬dHZHZHZ‹
  2. ÁõìÿÿHÁõÜCbt ÿÿÁô•ÿ-ZÿÿÿFrederique Courard HaurixHHÚ(ÿáÿâùFG(üHHØ(d'`ΔÿÿÂE•∫l2/ÀO! ÁÁõØÁõ !ÿÄ$Áõ OPffÿñÂIΔÁVP ÁõÔ4°ÿÿÿÿÿÿÿÿ4NN¬DSETb”b™di¶œÁõ˘Áõ‰Áõ√Áõl°TÁõ@"I °TÀP/J 8°TÀΔ3R¯°TÁõ(0Mfl°TÁõ86R ’°TÁó˛6R'ç°TÁõ46R.ì°TÁó`6R4ܰTÁõD6R:B°TÁõ$6R    ?5°TÁõà6R
  3. E”°TÁõH6R M)°TÁõ6R SI°TÁõ<6R
  4. Za°TÁõ6R`•°TÁôx&ñ°+          
  5.  M N o ˙ ¨ Ñ Ò X Y  ˆ  
  6.   Á Âûüˇı/0îï
  7.     N    O
  8. À
  9. Á 3 4 5 6 7 8 9 : l m
  10. M
  11. ≈ 
  12. º 
  13. î ! 2 C ∂ ¯ ß ú    # $ B [ wx"%& º» cd&˙&Î&Ï&≤&¿"ÕÖ*GH*´*µ*"/"0*q*r*Ë"Ì"Í ΠÏ å ú  & ; R i | ∂ Δ Ì Í ‡ fl Y ´  , m n ∏ ≤ › " # T Ω Ì Í  3 D W X s Δ ˜ ˘ π  : b ‰ Æ È ñ " Z ∫ √ ª ¿ Õ ã ä å    *  ,  B  C  }  ’  Æ !  ! ! ! ! ![ !® !Á !à!ê "5 "p "“ "µ "ë "í #9 #~ #ı #ƒ #à $ $ $] $∞ $¶ $Ñ $◊ $Ø $ò %F %a %n %… %¨ %í & &3 &L &N &U &u &{ &© &ò '2 'm '¢ 'ç ( (E (L (R (} (∞ ( (æ (ü ) )7 )= )B )k )£ )© )° )Ç * *? *q *x *~ *© *Ó *† + +T +q +˝ +¡ +Ê +Ø , ,, ,V ,  ,ä - -3 -9 -c -u -fi .- .? .V .[ .{ .˝ .ì / / /( /o /∫ /‘ /« /‡ 0 0 04 0] 0k 0q 0¥ 0÷ 1 1 1` 1’ 2 2 2 2C 2r 2“ 2† 2â 3 3@ 3t 3z 3˘ 3µ 4 4
  14.  4% 4+ 4- 4. 4/ 4| 4} 4∂ 4Œ 4ª 4Á 4Ü 4† 4fi 5" 5X 5u 5Δ 5¬ 5Æ 5Ç 5› 5ñ 6
  15.  6' 6( 6≈ 6¢ 6£ 6ê 7 7" 7> 7X 7Y 7≈ 7¨ 7© 7Ñ 7› 8 8 8 85 8N 8O 8‚ 8Π8Ï 8‹ 8é 8ê 9  9! 94 9B 9C 9D 9‰ 9Π: :  :B :C :Y :l :∑ : :¨ :Ç :‹ ; ;; ;T ;l ;√ ;π ;Ñ ;ì ;õ < <T <U <n <„ <§ <Ë <ì <õ = == =[ =e =j =q =s =t =Á = =î =ñ >; >p >q >ı >¡ >¢ >€ >» >π >› >ñ ?
  16.  ?  ?5 ?6 ?Ω ?√ ?Ï ?‹ @ @ @6 @< @˝ @Ô @Ú @Û A# A$ Ax A¢ A£ A¨ AÍ AÓ Aé B  B B Bu Bv B˘ B´ B≤ C Cl C’ CÔ D" Ds D E Ed E” Eû F F= F] F« FØ G# G] Gg G∞ G  G≤ Gí H H2 HH Hw HŸ Hπ HÒ I I IF I\ I— I¡ I‹ Iæ J J  J? Ju JÊ K1 Kz K• K∑ K√ KÓ L Li L L≠ L∞ L® L¯ L› M) M* M+ Mu M⁄ M∂ M¢ M£ Mï M› NO NQ Nk N≥ N˛ Nú O  O O OY O¢ O€ OÁ OÌ P P< PV Pi P| P} P˙ P’ PΠQ
  17.  Q. Qv QŒ Q¬ Q” Q´ Qµ QÓ Q› Qò R4 RM R“ S S SP Sc Sv S≈ S‚ S¿ T T
  18.  T  T2 Tƒ TÕ TÛ Tù U UX U| U“ Uµ U¶ Uæ Uç V! V4 VH Vy V‘ V¡ V¢ V› W W` W¢ W¨ WÚ WÛ Wó W‡ X0 XG Xz XŒ XÄ Y% Yh Y¯ YÆ Yù Z Z. Za Zu Z≈ Z∏ [$ [l [~ [ [È [ü \ \/ \R \z \‘ \£ ] ]\ ]s ]  ]· ]Ó ^( ^. ^o ^x ^˘ ^â ^û _# _D _R _\ _b _u _v _w _Ω _≈ _ı _ƒ _º _Ë _fi _ï `  ` `C `D `r `• `„ `‰ `£ `° `±"`”"`“`»"`πa"a"a"aaMa≈aÂbbsbt-bu-bv"b∑ bÙ bÚ c c cˆ c˜ d d    3ddidÈ K4à6à6à6à89    4 à;•à=à;L @M
  19. A^
  20. An
  21. A˙
  22. àD§
  23. AÑ
  24. Aæ
  25. Aì
  26. E
  27. AX
  28. A
  29. A 
  30. F
  31. 
  32. A
  33. AÁ
  34. A    HúàJû Oü
  35. Sı
  36. S0
  37. SÑ
  38. Wà
  39. Sï
  40. S 
  41. S    M
  42. W    N
  43. S
  44. h
  45. ^
  46. r
  47. S
  48. u
  49. ^
  50. ¬
  51. S
  52. Á
  53. S 2 a 3
  54. S 5
  55. e :òh ko l O m
  56. e ~
  57. e ”
  58. q
  59. 
  60. e
  61. L O
  62. Nr
  63. ≈r
  64. îr2r∂rßrr#rBrv
  65. sw Ox
  66. e»    wÁ
  67. e
  68.  O Oàz$|% O&
  69. ÉB    ÊM
  70. ÉR    Ê]
  71. É≈    Ê‚
  72. É’
  73. sº O»r
  74. Ì O
  75. Í
  76. 
  77. e    w&
  78. eT    wW
  79. eg    wp
  80. e—    wˆ
  81. eƒ    w¥
  82. eß    wè
  83. eö    wÿ
  84. e&    w/
  85. eb OdÎÍ ÏÏ
  86. ‹ü    Ñ
  87. ‹     Ñ
  88. ‹Y    Ñd
  89. ‹ˆ    Ñƒ
  90. ‹Ú    Ñã
  91. ‹≤ Ï¿àzÔ|Õ OÖ
  92. ÒG
  93. eH
  94. Òc
  95. Óg
  96. Òµ
  97. àÔº
  98. S
  99. Ò
  100. e OòÕ0
  101. Òq
  102. àÖx
  103. ÒË|Ì    ØÍ    ÙΠ   Ù`°
  104. s`±òÕ`“òh`º Ú`» Û`π
  105. ea Oa Ûa àÜa Ûa
  106. Sa
  107. ^a√
  108. Sb
  109. ^b^
  110. Sbt †bv àÜb≥ Ûb∑
  111. Ac˜
  112. Ad fid     àßd àd
  113. Sdh adi f;Áõx;AÁõ•|?Áôp    »XÁôt
  114. ˇÁôl°lÁôhVÁõ≥r`Áõ|ÒxÁôTJˆÁõh!à¬Áõd%‘ÀÁô‹)L‹ÁôÔ-ÜÁõ`0øáÁôÌ4ÙæÁõ\8¿êÁôÀ<©íÁôÄ@ˆïÁôÈD∑ïÁôπHtîÁó LbïÁô¸PQ”ÁõpTxÁôàW{LÁõPZÇ<ÁõT^3ÁõXa64ÁõL;
  115.  
  116.  
  117.  
  118.  
  119.  
  120.  
  121.  
  122.  
  123.  
  124. T E C H N O T E :
  125. Adding Items to the Printing ManagerÕs Dialogs
  126.  
  127. By Lew Rollins & Ginger Jernigan
  128. Revised by Ingrid Kelly & Dave Polaschek 
  129.   
  130. Apple Developer Technical Support (DTS)    
  131.  
  132. This Technote, originally Technote PR 09 - Print Dialogs: Adding Items, discusses how to add items to the Printing ManagerÕs dialogs.
  133.  
  134. When the Printing Manager was initially designed, great care was taken to make the interface to the printer drivers as generic as possible in order to allow applications to print without being device-specific. There are times, however, when this type of non-specific interface interferes with the flexibility of an application. An application may require additional information before printing which is not part of the general Printing Manager interface. This Note describes a methoAd that an application can use to add its own items to the existing style and job dialogs.
  135.  
  136. This revised Technote reflects the current Macintosh Printing Manager and uses C code instead of the original Pascal.
  137.  
  138.  
  139.  
  140. You can download a complete version of the code in this Technote, PDlog Expand Ä sample code, by clicking on the icon in the Downloadables section at the very end of this Note. 
  141.  
  142. Printing Manager Compatibility Guidelines for the Future
  143.  
  144. To begin with, you need to be aware of some guidelines that will increase your chances of being compatible with future revisions of Macintosh Printing Manager: 
  145.  
  146. ¥    Only add items to the dialogs as described in this technical note. Any other method will decrease your chances of compatibility in the future.
  147.  
  148. ¥    Do not change the position of any item in the current dialogs. This means ?donÕt delete items from the existing item list or add items in the middle. Add items only at the end of the list.
  149.  
  150. ¥    DonÕt count on an item retaining its current position in the list. If you depend on the Draft button being a particular number in the ImageWriterÕs style dialog item list, and we change the Draft buttonÕs item number for some reason, your program may no longer function correctly.
  151.  
  152. ¥    DonÕt use more than half the screen height for your items. Apple reserves the right to expand the items in the standard print dialogs to fill the top half of the screen. Even though LaserWriter 8.4 changes the print dialogs, in order to be compatible with older drivers, you still need to maintain this half-screen rule.
  153.  
  154. ¥    Under LaserWriter 8.4.x the print dialogs have been completely redesigned. If you add items to the print dXialog 'legally', your items are added to a pane that has the name of your application. If you donÕt add them as recommended in this Note, there will be problems. Please see develop 27 - Print Hints: The All-New LaserWriter Driver Version 8.4 for more details. 
  155.  
  156. ¥ Applications should not assume that the print dialogÕs foreground color is black or that the background color is white when they erase their controls. Furthermore, applications should not change the foreground or background colors because other items in the dialog rely on these colors. If an application changes them, the print dialog may end up with strange colors.
  157.  
  158.  
  159.  
  160.  
  161.  
  162.  
  163.  
  164. The Heart of the Print Dialogs: The TPrDlg Record
  165.  
  166. Before discussing how the dialogs work, it is important to know that at the heart of the print dialogs is a little-known data structure partially documented in Printiˇng.h. ItÕs a record called TPrDlg and it looks like this:
  167.  
  168. struct TPrDlg {
  169.     DialogRecord    Dlg;            /*The Dialog window*/
  170.     ModalFilterUPP    pFltrProc;        /*The Filter Proc.*/
  171.     PItemUPP    pItemProc;        /*The Item evaluating proc.*/
  172.     THPrint        hPrintUsr;        /*The user's print record.*/
  173.     Boolean        fDoIt;
  174.     Boolean        fDone;
  175.     long            lUser1;        /* Four longs reserved by Apple for                                 global data */
  176.                         /* to hang global data.*/
  177.     long            lUser2;        /* More stuff needed by the */
  178.                         /*printing dialog.*/
  179.     long            lUser3;                        
  180.     long            lUser4;
  181. };
  182.  
  183. typedef struct TPrDlg TPrDlg;
  184. typedef TPrDlg *TPPrDlg;
  185. typedef TPrDlg *TPPrDlgRef;
  186.  
  187. All of the information pertaining to a print dialog is kept in the TPrDlg record. This record will be referred to frequently in the discussion below.
  188.  
  189.  
  190. How the Dialogs Work
  191.  
  192. When your application calls PrStlDialog and PrJobDialog, the printer driver calls a routine called PrDlgMain. This function is declared asl follows:
  193.  
  194.     extern pascal Boolean PrDlgMain(THPrint hPrint, PDlgInitUPP pDlgInit);
  195.  
  196. PrDlgMain first calls the pDlgInit routine to set up the appropriate dialog (in Dlg), dialog hook (pItemProc) and dialog event filter (pFilterProc) in the TPrDlg record (shown above). For the job dialog, the address of PrJobInit is passed to PrDlgMain. For the style dialog, the address of PrStlInit is passed. These routines are declared as follows:
  197.  
  198.     extern pascal TPPrDlgRef PrJobInit(THPrint hPrint);
  199.     extern pascal TPPrDlgRef PrStlInit(THPrint hPrint);
  200.  
  201. After the initialization routine sets up the TPrDlg record, PrDlgMain calls ShowWindow (the window is initially invisible), then it calls ModalDialog, using the dialog event filter pointed to by the pFltrProc field. When an item is hit, the routine pointed to by the pItemProc field is called and the items are handled appropriately.V When the OK button is hit (this includes pressing Return or Enter) the print record is validated. The print record is not validated if the Cancel button is hit.
  202.  
  203. Adding Your Own Items
  204.  
  205. To modify the print dialogs, you need to change the TPrDlg record before the dialog is drawn on the screen. You can add your own items to the item list, replace the addresses of the standard dialog hook and event filter with the addresses of your own routines and then let the dialog code handle the necessary functions to make the items visible in your print dialog. 
  206.  
  207. The example codeÕs initialization function adds items to the dialog item list, saves the address of the standard dialog hook (in our global variable prPItemProc) and puts the address of our dialog hook into the pItemProc field of the TPrDlg record. Please note that your dialog hook must call the s`tandard dialog hook to handle all of the standard dialogÕs items.
  208.  
  209. Note: If you wish to have an event filter, use the same method that you would for a dialog hook.
  210.  
  211.  
  212.  
  213. The C Example Program
  214.  
  215. Here is an example (written in C) that modifies the job dialog. 
  216.  
  217. Note: The same code works for the style dialog if you globally replace ÔJobÕ with ÔStlÕ.
  218.  
  219.  
  220.  
  221.  
  222. #include <Printing.h>
  223. #include <Dialogs.h>
  224. #include <Gestalt.h>
  225. #include <MixedMode.h>
  226. #include <SegLoad.h>
  227. #include <Resources.h>
  228. #include <ToolUtils.h>
  229. #include <Fonts.h>
  230. #include <Lists.h>
  231.  
  232. static TPPrDlg PrtJobDialog;    /* pointer to job dialog */
  233.  
  234. /* Declare ÔpascalÕ functions and procedures */
  235.  
  236. extern short    Append_DITL(TPPrDlg, short);        /* Our AppendDITL function.         */
  237. extern pascal   TPPrDlg MyJobDlgInit(THPrint);      /* Our extention to PrJobInit.      */
  238. extern pascal   void MyJobItemxs(TPPrDlg, short);    /* Our modal item handler.          */
  239. extern OSErr    Print(void);
  240. pascal void MyListDraw(WindowPtr theWindow, short itemNo); //mxm
  241.  
  242. #define MyDITL 256  /* resource ID of my DITL to be spliced onto job dialog */
  243.  
  244. ListHandle  gList = nil;                /* mxm */
  245. UserItemUPP myDrawListUPP = nil;        /* mxm */
  246.  
  247. THPrint hPrintRec;  /* handle to print record */
  248. long prFirstItem;   /* save our first item here */
  249. PItemUPP prPItemProc;   /* we need to store the old itemProc here */
  250.  
  251. /*-----------------------------------------------------------------------*/
  252.     WindowPtr   MyWindow;
  253.     OSErr   err;
  254.     Str255  myStr;
  255.  
  256. #if PRAGMA_ALIGN_SUPPORTED
  257. #pragma options align=mac68k
  258. #endif
  259.  
  260. typedef struct dialog_item_struct {
  261.     Handle  handle; /* handle or procedure pointer for this item */
  262.     Rect    bounds; /* display rectangle for this item */
  263.     char    typeˆ;   /* item type - 1 */
  264.     char    data[1];    /* length byte of data */
  265. } DialogItem, *DialogItemPtr, **DialogItemHandle;
  266.  
  267. typedef struct append_item_list_struct {
  268.     short   max_index; /* number of items - 1 */
  269.     DialogItem  items[1]; /* first item in the array */
  270. } ItemList, *ItemListPtr, **ItemListHandle;
  271.  
  272. typedef union signed_byte_union {
  273.     short   integer;
  274.     char    bytes[2];
  275. } ByteAccess;
  276.  
  277.  
  278. static Boolean append_exits(void);
  279. static Boolean append_exits(void)
  280. {
  281.     long    response;
  282.  
  283.     if (Gestalt(gestaltDITLExtAttr,&response) == noErr) {
  284.         return !!(response & (1 << gestaltDITLExtPresent));
  285.     } else {
  286.         return false;   /* simple-minded, but hey, so am I. -DaveP */
  287.     }
  288. }
  289.  
  290.  
  291. /*  This routine appends all of the items of a specified DITL   */
  292. /*  onto the end of a specified DLOG Ñ We donÕt even need to know the format    */
  293. /*  of the DLOG */
  294.  
  295. /*  this will be done in 3 st¬eps:   */
  296. /*  1. append the items of the specified DITL onto the existing DLOG    */
  297. /*  2. expand the original dialog window as required    */
  298. /*  3. return the adjusted number of the first new user item    */
  299.  
  300. short Append_DITL(TPPrDlg dialog, short item_list_ID)
  301. {
  302.     ItemListHandle  append_item_list;   /* handle to DITL being appended */
  303.     ItemListHandle  dlg_item_list;  /* handle to DLOG's item list */
  304.     short           first_item;
  305.  
  306.     dlg_item_list = (ItemListHandle)((DialogPeek)dialog)->items;
  307.     first_item = (**dlg_item_list).max_index + 2;
  308.  
  309.     append_item_list = (ItemListHandle)GetResource('DITL', item_list_ID);
  310.     if ( append_item_list == NULL ) {
  311.         DebugStr("\pError loading DITL resource");
  312.         return first_item;
  313.     }
  314.  
  315.     if (append_exits()) {
  316.         AppendDITL((DialogPtr)dialog, (Handle) append_item_list, appendDITLBottom);
  317.         return first_item;
  318.     } else {
  319.         Point       offset;
  320.   À      Rect        max_rect;
  321.         DialogItemPtr   item;   /* pointer to item being appended */
  322.         short       new_items, data_size, i;
  323.         ByteAccess  usb;
  324.         OSErr       err;
  325.  
  326.     /*
  327.         Using the original DLOG
  328.      
  329.         1. Remember the original window Size.
  330.         2. Set the offset Point to be the bottom of the original window.
  331.         3. Subtract 5 pixels from bottom and right, to be added
  332.         back later after we have possibly expanded window.
  333.         4. Get working Handle to original item list.
  334.         5. Calculate our first item number to be returned to caller.
  335.         6. Get locked Handle to DITL to be appended.
  336.         7. Calculate count of new items.
  337.     */
  338.      
  339.         if (dialog == NULL) ExitToShell();
  340.      
  341.         max_rect = ((DialogPeek)dialog)->window.port.portRect;
  342.         offset.v = max_rect.bottom;
  343.         offset.h = 0;
  344.         max_rect.bottom -= 5;
  345.         max_rect.right -= 5;
  346.      
  347.     
  348.         HL‹ock((Handle)append_item_list);
  349.         new_items = (**append_item_list).max_index + 1;
  350.      
  351.     /*
  352.         For each item,
  353.         1. Offset the rectangle to follow the original window.
  354.         2. Make the original window larger if necessary.
  355.         3. fill in item handle according to type.
  356.     */
  357.      
  358.         item = (**append_item_list).items;
  359.         for ( i = 0; i < new_items; i++ )
  360.         {
  361.             OffsetRect(&item->bounds, offset.h, offset.v);
  362.             UnionRect(&item->bounds, &max_rect, &max_rect);
  363.             usb.integer = 0;
  364.             usb.bytes[1] = item->data[0];
  365.      
  366.             switch ( item->type & 0x7F )
  367.             {
  368.                 case ctrlItem + btnCtrl :
  369.                 case ctrlItem + chkCtrl :
  370.                 case ctrlItem + radCtrl :
  371.                     item->handle = (Handle)NewControl((DialogPtr) dialog,
  372.                         &item->bounds, (StringPtr)item->data, true,
  373.                         0, 0, 1, item->type & 0x03, 0);
  374. Ü                break;
  375.      
  376.                 case ctrlItem + resCtrl :
  377.                 {
  378.                     item->handle = (Handle)GetNewControl(*(short*)(item->data + 1), (DialogPtr) dialog);
  379.                     (**(ControlHandle)item->handle).contrlRect = item->bounds;
  380.                 }
  381.                 break;
  382.     
  383.                 case statText :
  384.                 case editText :
  385.                     err = PtrToHand(item->data + 1, &item->handle, usb.integer);
  386.                 break;
  387.     
  388.                 case iconItem :
  389.                     item->handle = GetIcon(*(short*)(item->data + 1));
  390.                 break;
  391.      
  392.                 case picItem :
  393.                     item->handle = (Handle)GetPicture(*(short*)(item->data + 1));
  394.                 break;
  395.      
  396.                 default :
  397.                     item->handle = NULL;
  398.             }
  399.      
  400.             data_size = (usb.integer + 1) & 0xFFFE;
  401.             item = (DialogItemPtr)((char*)item + data_size + sizeof(DialogItem));
  402.  á       }
  403.      
  404.      /* We need to subtract the short below because otherwise the size of the DITL count
  405.      ** gets factored in twice, and the resulting DTIL has two bytes of garbage appended
  406.      ** to it. This is a problem with the original TN#95 code as well.
  407.      */
  408.      
  409.         err = PtrAndHand((**append_item_list).items,
  410.                         (Handle)dlg_item_list,
  411.                         GetHandleSize((Handle) append_item_list)
  412.                         - sizeof(short));
  413.     
  414.         (**dlg_item_list).max_index += new_items;
  415.         HUnlock((Handle) append_item_list);
  416.         ReleaseResource((Handle) append_item_list);
  417.      
  418.         max_rect.bottom += 5;
  419.         max_rect.right += 5;
  420.         SizeWindow((WindowPtr) dialog, max_rect.right, max_rect.bottom, true);
  421.      
  422.         return first_item;
  423.     }
  424. }
  425.  
  426.  
  427. /*------------------------------------------------------------------------*/
  428.  
  429. OSErr Print(void)
  430. {
  431.     TPPrPort    pPrPort;
  432.     Rect        aRect;
  433.     TPrStatus   theStatuæs;
  434.  
  435.  
  436.     /* call PrJobInit to get pointer to the invisible job dialog */
  437.     hPrintRec = (THPrint)(NewHandle(sizeof(TPrint)));
  438.     PrintDefault(hPrintRec);
  439.     PrValidate(hPrintRec);
  440.     if (PrError() != noErr)
  441.         return PrError();
  442.  
  443.     PrtJobDialog = PrJobInit(hPrintRec);
  444.  
  445.     if (PrError() != noErr)
  446.         return PrError();
  447.  
  448.     if (!PrDlgMain(hPrintRec, NewPDlgInitProc(MyJobDlgInit))) /* this line does all the stuff */
  449.         return iPrAbort;
  450.  
  451.     if (myDrawListUPP) {  /* get rid of our user item draw proc mxm */
  452.         DisposeRoutineDescriptor(myDrawListUPP);
  453.     } 
  454.     if (PrError() != noErr)
  455.         return PrError();
  456.  
  457.     pPrPort = PrOpenDoc(hPrintRec, NULL, NULL);
  458.     PrOpenPage(pPrPort, NULL);
  459.  
  460.     aRect = (*hPrintRec)->prInfo.rPage;
  461.     InsetRect(&aRect, 20, 20);
  462.     PenSize(4, 4);
  463.     FrameRect(&aRect);
  464.  
  465.     PrClosePage(pPrPort);
  466.     PrCloseDoc(pPrPort);
  467.  
  468.     if (!PrError() && (*hPrintRec)->prJob.bJDocLoop == bSpoolLoop)
  469.         PrPicFile(hPrintRec, NULL, NULL, NULLê, &theStatus);
  470.  
  471.  
  472. /* that's all for now */
  473.  
  474.     if (hPrintRec) DisposeHandle((Handle) hPrintRec);
  475.  
  476.     return(noErr);
  477. } /* Print */
  478.  
  479.  
  480. //-----------------------------------------------------------------------------
  481. pascal void MyListDraw(WindowPtr theWindow, short itemNo)
  482. //-----------------------------------------------------------------------------
  483. {
  484. #pragma unused (theWindow,itemNo)
  485.  
  486.     short   itemType;
  487.     Handle  itemH;
  488.     Rect    itemBox,r;  
  489.     Point   pt;
  490.     ControlRef cr;
  491.     RgnHandle clip = NewRgn();
  492.         
  493.     GetDialogItem((DialogPtr) PrtJobDialog,itemNo,&itemType,&itemH,&itemBox);
  494.     r = theWindow->portRect;
  495.     pt.h = itemBox.left;
  496.     pt.v = itemBox.top;
  497.     cr = gList[0]->vScroll;
  498.     MoveControl(cr,itemBox.right-15,itemBox.top-1);
  499.     ShowControl(cr);
  500.     if (PtInRect(pt,&r)) {
  501.         
  502.         gList[0]->rView = itemBox;
  503.         gList[0]->rView.right -=15;  //inset for scroll bar
  504.  
  505.         ShowControl(cr);
  506.         LSetDrawingMode(true,gList);
  507.         if (clip) {
  508.   í          RectRgn(clip,&itemBox);
  509.             LUpdate(clip,gList);
  510.         
  511.             InsetRect(&itemBox,-1,-1);
  512.             FrameRect(&itemBox);
  513.             DisposeRgn(clip);
  514.         }
  515.     
  516.     } 
  517. }
  518.  
  519. /*------------------------------------------------------------------------*/
  520.  
  521. pascal TPPrDlg MyJobDlgInit(THPrint hPrint)
  522. /*
  523.     this routine appends items to the standard job dialog and sets up the
  524.     user fields of the printing dialog record TPRDlg
  525.  
  526.     This routine will be called by PrDlgMain
  527. */
  528.  
  529. {
  530. #pragma unused(hPrint)
  531.  
  532.     short   firstItem;  /* first new item number */
  533.  
  534.     short   itemType, item;
  535.     Handle  itemH;
  536.     Rect    itemBox;
  537.  
  538.     firstItem = Append_DITL(PrtJobDialog, MyDITL); /* call routine to do this */
  539.  
  540.     prFirstItem = firstItem; /* save this so MyJobItems can find it */
  541.  
  542.     /* now we'll set up our DITL items -- The radio buttons */
  543.  
  544.     for (item = 5; item <= 7; item++)
  545.     {
  546.         GetDialogItem((DialogPtr) PrtJobDialog,firstItem + item -1,&itemType,&itemH,&itemBïox);
  547.         SetCtlValue((ControlHandle) itemH, (item == 5));
  548.     }
  549.  
  550.     /* now we'll set up the second of our DITL items -- The checkbox */
  551.  
  552.     GetDialogItem((DialogPtr) PrtJobDialog,firstItem +2,&itemType,&itemH,&itemBox);
  553.     SetCtlValue((ControlHandle) itemH,1);
  554.  
  555.     
  556.     // here is the list stuff (mxm) 
  557.     {
  558.         Rect bounds ;
  559.         Point theCell = {16,200};
  560.         
  561.         
  562.         GetDialogItem((DialogPtr) PrtJobDialog,firstItem +8,&itemType,&itemH,&itemBox);
  563.  
  564.         SetRect(&bounds,0,0,1,0);
  565.         itemBox.right -=15;
  566.          
  567.         gList  = LNew(&itemBox,&bounds,theCell,0,(GrafPtr)PrtJobDialog,false,false,false,true);
  568.         if (gList) {    // this is how you need to do the scroll-bar so it'll
  569.                         // move off correctly with LaserWriter 8.4 and later
  570.                         //
  571.                         // The theory is that we have another user item which
  572.                         // has the handle for the control item for the scrollbar
  573.                   ï      // for the list. This way, the scroll bar gets redrawn
  574.                         // in the right order, so it realises it's off the panel
  575.                         // when it is. If you don't have this code, the scroller
  576.                         // gets drawn, then the list gets moved, so you get a
  577.                         // phantom scroller in the dialog. -DaveP 9/3/96
  578.             short   scrollType;
  579.             Handle  scrollHandle;
  580.             Rect    scrollRect;
  581.             GetDialogItem((DialogPtr)PrtJobDialog,firstItem + 9, &scrollType,
  582.                 &scrollHandle, &scrollRect);
  583.             SetDialogItem((DialogPtr)PrtJobDialog,firstItem + 9, ctrlItem,
  584.                 (Handle) (**gList).vScroll, &scrollRect);
  585.         }
  586.         LAddRow(9,0,gList);
  587.         SetPt(&theCell,0,0);
  588.         // Lets add some data
  589.         LSetCell("Testing 1",9,theCell,gList);
  590.         theCell.v ++;
  591.         LSetCell("Testing 2",9,theCell,gList);
  592.         theCell.v ++;
  593.         LSetCell("Testing 3",9,theCell,gListî);
  594.         theCell.v ++;
  595.         LSetCell("Testing 4",9,theCell,gList);
  596.         theCell.v ++;
  597.         LSetCell("Testing 5",9,theCell,gList);
  598.         theCell.v ++;
  599.         LSetCell("Testing 6",9,theCell,gList);
  600.         theCell.v ++;
  601.         LSetCell("Testing 7",9,theCell,gList);
  602.         theCell.v ++;
  603.         LSetCell("Testing 8",9,theCell,gList);
  604.         theCell.v ++;
  605.         LSetCell("Testing 9",9,theCell,gList);  
  606.         
  607.         LActivate(true,gList);
  608.         myDrawListUPP =  NewUserItemProc(MyListDraw);
  609.                                                                                     
  610.         SetDialogItem((DialogPtr) PrtJobDialog,firstItem + 8,itemType,(Handle)myDrawListUPP,&itemBox);
  611.                                                                         
  612.     }
  613.     
  614. /*
  615.     Now comes the part where we patch in our item handler. We have to save
  616.     the old item handler address, so we can call it if one of the standard
  617.     items is hit, and put our item handler's address in pItemProc fiïeld of
  618.     the TPrDlg struct
  619. */
  620.  
  621.     prPItemProc = PrtJobDialog->pItemProc;
  622.  
  623. /* Now we'll tell the modal item handler where our routine is */
  624.     PrtJobDialog->pItemProc = NewPItemProc(MyJobItems) ;
  625.  
  626.  
  627. /* PrDlgMain expects a pointer to the modified dialog to be returned...*/
  628.     return PrtJobDialog;
  629.  
  630. } /*myJobDlgInit*/
  631.  
  632. /*-----------------------------------------------------------------------*/
  633.  
  634.  static pascal Boolean  testFilter(DialogPtr theDialog, EventRecord *theEvent, short *itemHit)
  635. {
  636. #pragma unused(theDialog)
  637. #pragma unused(theEvent)
  638. #pragma unused(itemHit)
  639. //  DebugStr("\pMy filter proc got called");    // This gets called a lot if you uncomment it
  640.     return false;
  641. }
  642.  
  643. static pascal void testDialogUserItem(WindowPtr theWindow, short itemNo);
  644. static pascal void testDialogUserItem(WindowPtr theWindow, short itemNo)
  645. {
  646.     if (itemNo != 4) return;
  647.     else {
  648.         short   oldFont = ((GrafPtr)theWindow)->txFont;
  649.         short   oldSize = ((GrafPtr)theWindow)->txSize;
  650.         short   itemT”ype;
  651.         Handle  h;
  652.         Rect    r;
  653.  
  654.         SetPort(theWindow);
  655.         TextFont(GetAppFont());
  656.         TextSize(9);
  657.         GetDialogItem((DialogPtr)theWindow,4,&itemType,&h,&r);
  658.         MoveTo(r.left,r.bottom);
  659.         DrawString("\p<http://www.winternet.com/~dask/poohsnif.html>");
  660.         TextFont(oldFont);
  661.         TextSize(oldSize);
  662.     }
  663. }
  664.  
  665. static void TestDialog(void);
  666. static void TestDialog(void)
  667. {
  668.     DialogPtr   theDialog = GetNewDialog(257,nil,(WindowPtr)-1L);
  669.     short   itemHit = 0;
  670.     ModalFilterUPP  mySubDialogFilterProc = nil;    // NewModalFilterProc(testFilter); // for testing
  671.     UserItemUPP     mySubDialogUserProc = NewUserItemProc(testDialogUserItem);
  672.  
  673.     {       // set up the user item to draw the outline around the ok button
  674.         short   t;
  675.         Handle  h;
  676.         Rect    r;
  677.         
  678.         GetDialogItem(theDialog,4,&t,&h,&r);
  679.         SetDialogItem(theDialog,4,t,(Handle)mySubDialogUserProc,&r);x
  680.     }
  681.  
  682.     SetDialogDefaultItem(theDialog,1);
  683.     while((itemHit != 1) && (itemHit != 2)) {   // a WAY bad way of seeing if we're done, but I'm in a hurry
  684.         ModalDialog(mySubDialogFilterProc, &itemHit);
  685.     }
  686.     DisposeDialog(theDialog);
  687.     if (mySubDialogFilterProc != nil)
  688.         DisposeRoutineDescriptor(mySubDialogFilterProc);
  689.     if (mySubDialogUserProc != nil)
  690.         DisposeRoutineDescriptor(mySubDialogUserProc);
  691. }
  692.  
  693. /* here's the analogue to the SF dialog hook */
  694.  
  695. pascal void MyJobItems( TPPrDlg theDialog, short itemNo )
  696. { /* MyJobItems */
  697.     short   myItem;
  698.     short   firstItem, item, itemType, theValue;
  699.     Handle  itemH;
  700.     Rect    itemBox;
  701.  
  702.     firstItem = prFirstItem;    /* remember, we saved this in myJobDlgInit */
  703. //  DebugStr("\p Looking at the item...");
  704.     myItem = itemNo-firstItem+1;    /* "localize" current item No */
  705.     if (myItem > 0) /* if lLocalized item > 0, it's one of ours */
  706.     {
  707.         /* find out which of our items was hit */
  708.  
  709.         switch (myItem)
  710.         {
  711.             case 1:         /*  Static text.    */
  712.                 break;
  713.             case 2:         /*  Edit text.      */
  714.                 break;
  715.             case 3:         /*  Check box.      */
  716.                     GetDialogItem((DialogPtr) theDialog,firstItem +2,&itemType,&itemH,&itemBox);
  717.                     theValue = GetCtlValue((ControlHandle) itemH);
  718.                     SetCtlValue((ControlHandle) itemH, theValue != 1);
  719.                 break;
  720.             case 4:         /*  Push button.    */
  721.                 TestDialog();
  722.                 break;
  723.             case 5:         /*  Radio buttons   */
  724.             case 6:
  725.             case 7:
  726.                 for (item = 5; item <= 7; item++) {
  727.           <          GetDialogItem((DialogPtr) theDialog,firstItem +item -1,&itemType,&itemH,&itemBox);
  728.                     SetCtlValue((ControlHandle) itemH, item == myItem);
  729.                 }
  730.                 break;
  731.             case 8:         /*  Edit text.      */
  732.             case 9:         /*  Our List.       */ 
  733.                 {   
  734.                     Point pt;
  735.                     GetMouse(&pt);
  736.                     LClick(pt,0,gList);
  737.                 }
  738.                 break;
  739.             case 10:        /* our list's scroll bar. We don't need to do anything, but we need
  740.                             * to have some code here so we don't hit the default case */
  741.                 break;
  742.             default: Debugger(); /* OH OH */
  743.         } /* switch */
  744.     } /* if (myItem > 0) */
  745.     else /* chain to standard item handler, whos3e address is saved in prPItemProc */
  746.     {
  747.         CallPItemProc(prPItemProc,(DialogPtr)theDialog, itemNo);
  748.         
  749.         if (theDialog->fDone) {
  750.             // we're going away, need to clean up our scroll bar and list
  751.             if (gList) {
  752.                 (**gList).vScroll = 0L;
  753.                 LDispose(gList);
  754.             }
  755.         }
  756.     }
  757. } /* MyJobItems */
  758.  
  759.  
  760. void main(void)
  761. {
  762.     Rect    myWRect;
  763.  
  764.     InitGraf(&qd.thePort);
  765.     InitFonts();
  766.     InitWindows();
  767.     InitMenus();
  768.     InitDialogs((long)nil);
  769.     InitCursor();
  770.     SetRect(&myWRect,50,260,350,340);
  771.  
  772.     /* call the routine that does printing */
  773.     PrOpen();
  774.     err = Print();
  775.  
  776.     PrClose();
  777. } /* main */
  778.  
  779.  
  780.  
  781. Summary
  782.  
  783. ThatÕs all there is to it. Now you can add items to the print dialogs.
  784.  
  785. Further Reference
  786.  
  787. ¥ Inside Macintosh: Imaging Wit4h QuickDraw, Chapter 9
  788. ¥ Inside Macintosh: Macintosh Toolbox Essentials, Chapter 6
  789. ¥ PDlog Expand sample code, included with this Technote.
  790. ¥ StdFileSaver sample code, available on the Developer CD Series: Tool Chest Edition.
  791. ¥ develop 27 - Print Hints: The All-New LaserWriter Driver Version 8.4  by Dave Polaschek.
  792.  
  793.  
  794.  
  795. Change History
  796. Originally written in November 1986, as Technote #95 "Print Dialogs: Adding Items."
  797.  
  798. Revised in March 1988, Technote PR09 "Print Dialogs: Adding Items."
  799.  
  800. Accompanying code revised by Dave Hersey (1991), Dave Polaschek (1995,1996), Matt Mora (1996) and Ingrid Kelly (1996).
  801.  
  802. In October, 1996, this Technote was updated to reflect the current Macintosh Printing Manager and to use C code.
  803.  
  804. Acknowledgements
  805. Special thanks to Rich Blanchard, Paul Danbold, Matt Mora, and Dave Polaschek.
  806. ZÿÿN°DSET≠ÿÿ.H
  807. ,ÿÿÿÿÿÿÁôܰ√Úf˛(•°ÿÿ6ÿÿ*Úf˛DSET ÿÿ.HX(PL*+ÿÿÿÿÿÿÁôØ˛T°ÿÿ√ܰÿÿd°ÿÿ˘    ì°ÿÿ
  808.   t°ÿÿ ¨ü°ÿÿ0≥°ÿÿ¸ °ÿÿ@‰°ÿÿȰ    ÿÿP€°
  809. ÿÿØ,° ÿÿ` ´° ÿÿ è#<°
  810. ÿÿ#p%İÿÿ%ø(L°ÿÿU√°ÿÿ†°ÿÿe˘°ÿÿ    í
  811.  °ÿÿ u ¨°ÿÿ‡0°ÿÿ∑¸°ÿÿ
  812. @°ÿÿȰ    ÿÿP°
  813. ÿÿ¥Ø° ÿÿ-`° ÿÿ µ è°
  814. ÿÿ#=#p°ÿÿ%Å%ø°ÿÿ(M(•°ÿÿ6ÿÿ*Úf˛DSET≠ÿÿ.H
  815. "ÿÿÿÿÿÿÁôHÚf˛3°ÿÿÖÿÿ*Úf˛°34°3†°3†°3†°3†°3†°3†°3†°3†°3†°3†°3†°3†°3†°3†°3†DSETT@∑Áô4ÁôDÁô@Áô\°3Áô´2 ∑ /"    à0@|
  816. @Û‰ÿÔåDX‰Àl∞
  817. @Û‰ÿÔåDX‰Àl
  818. ∫Áô8∫
  819.  
  820. Technote  1080      ///          Release 1.0       © 1996   Apple Computer, Inc.      ///              ///          Page   of  
  821. FNTMCUTSDSUM1Frederique Courard HauriHDNISTYLâÿÿ@STYLÁô ÁôüÁôÁôdÁôäÁôìÁôôÁôørQÿÿΩ
  822. ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
  823. ÿÿÿÿf
  824. ÿÿÿÿ    
  825. ÿÿÿÿ
  826. ÿÿÿÿÿÿÿÿÿÿ    ÿÿÿÿ        ÿÿÿÿÿÿ
  827. $    ÿÿ7ÿÿÿÿ
  828. ÿÿÿÿ ÿÿÿÿ
  829. ÿÿ        ÿÿÿÿ
  830. 
  831. ÿÿÿÿ  ÿÿÿÿÿÿ
  832.  ÿÿÿÿÿÿ
  833. 
  834. ÿÿÿÿÿÿ
  835. ÿÿ%‹ÿÿÿÿÿÿ!0ÿÿÿÿ#0ÿÿÿÿ%0ÿÿÿÿ'0#ÿÿÿÿ(0#ÿÿÿÿ,0#    ÿÿÿÿ.0#
  836. ÿÿÿÿ10# ÿÿÿÿ20# ÿÿÿÿ50!
  837. ÿÿÿÿ70!ÿÿÿÿ:0%ÿÿÿÿ <0%ÿÿÿÿ%!>‹ÿÿÿÿÿÿ"?0>>ÿÿ#B0>>ÿÿ$C0>>ÿÿÿÿ%G0>Bÿÿ&I0>Bÿÿ'L0>B    ÿÿ(M0>B
  838. ÿÿ)N0>B ÿÿ*P0>B ÿÿÿÿ+R0>?&ÿÿÿÿ,T0>?'ÿÿÿÿ-V0>C(ÿÿ .X0>Cÿÿÿÿ%/[‹ÿÿÿÿÿÿ0\0[[)ÿÿÿÿ1]0[[*ÿÿÿÿ2_0[[*ÿÿÿÿ3b0[]+ÿÿÿÿ4c0[],ÿÿÿÿ5g0[],    ÿÿÿÿ6i0[],
  839. ÿÿÿÿ7l0[], ÿÿÿÿ8m0[], ÿÿÿÿ9n0[\-ÿÿÿÿ:p0[\-ÿÿÿÿ;t0[_+ÿÿÿÿ<v0[_,ÿÿÿÿ%=y‹ÿÿÿÿÿÿ>{0yy.ÿÿÿÿ?}0yyÿÿÿÿ@~0yyÿÿÿÿA0y}/    ÿÿÿÿB•0y}ÿÿÿÿC™0y}     ÿÿÿÿD≠0y}!    ÿÿÿÿE∞0y}"    ÿÿÿÿF≥0y}#    ÿÿÿÿG∑0y{0$
  840. ÿÿÿÿH∫0y{0%
  841. ÿÿÿÿIΩ0y~&    ÿÿÿÿJ√0y~'ÿÿÿÿ%K≈‹ÿÿÿÿ(ÿÿL…0≈≈1)ÿÿÿÿM—0≈≈*ÿÿÿÿN‘0≈≈+ ÿÿÿÿOŸ0≈—,ÿÿÿÿP⁄0≈—-ÿÿÿÿQ∂0≈—.ÿÿÿÿRΔ0≈—/ÿÿÿÿSŒ0≈—0ÿÿÿÿT‚0≈—1ÿÿÿÿU„0≈…26
  842. ÿÿÿÿV‰0≈…27
  843. ÿÿÿÿW0≈‘(4
  844. ÿÿÿÿXˆ0≈‘5
  845. ÿÿÿÿY˜‹ÿÿÿÿ(ÿÿZ˘0˜˜) ÿÿM[˙0˜˜*ÿÿÿÿ\˚0˜˜2ÿÿÿÿ]˝0˜˙,ÿÿÿÿ^˛0˜˙3ÿÿÿÿ_ˇ0˜˙8ÿÿÿÿ`ı0˜˙9ÿÿÿÿaƒ0˜˙:ÿÿÿÿb 0˜˘36
  846. ÿÿÿÿc¡0˜˚<ÿÿÿÿd¢‹ÿÿÿÿ
  847. ;ÿÿe£0¢¢4=ÿÿÿÿf€0¢¢
  848. >ÿÿÿÿg¥0¢€
  849.  ÿÿÿÿhœ0¢€
  850. !ÿÿÿÿi§0¢€
  851. "ÿÿÿÿj¨0¢€
  852. #ÿÿÿÿk©0¢£5Aÿÿÿÿlª0¢£5Bÿÿÿÿm«Øÿÿÿÿ
  853.     ÿÿn¬8««
  854.  ÿÿÿÿo–8««
  855.  ÿÿÿÿp®8««
  856. ÿÿÿÿq¯8««
  857. ÿÿÿÿr°8««
  858. ÿÿÿÿs±8««
  859. ÿÿÿÿt”8««
  860. ÿÿÿÿu“8««
  861. ÿÿÿÿv´8««
  862. ÿÿÿÿwµ8««
  863. ÿÿÿÿx¶8««
  864. ÿÿÿÿy·8««
  865. ÿÿÿÿz¸Øÿÿÿÿ6ÿÿ{’8¸¸7ÿÿÿÿ|º8¸¸8 ÿÿÿÿ}»8¸¸9!ÿÿÿÿ~π8¸¸:"ÿÿÿÿ∏8¸¸:#ÿÿÿÿ•≤8¸¸:%ÿÿÿÿ™¿8¸¸:&ÿÿÿÿ≠À8¸¸:'ÿÿÿÿ∞Á8¸¸:(ÿÿÿÿ≥Â8¸¸:)ÿÿÿÿ ∑ÃØÿÿÿÿ
  866. +ÿÿ∫Ä8ÃÃ
  867. ,ÿÿÿÿΩÅ8ÃÃ
  868. -ÿÿÿÿ√Æ8ÃÃ
  869. .ÿÿÿÿ≈Ç8ÃÃ
  870. 0ÿÿÿÿ…È8ÃÃ
  871. 1ÿÿÿÿ—    ÿÿ#ÿÿ—‘/ÿÿ#ÿÿÿÿŸ0ÿÿ$ÿÿÿÿ⁄Ëÿÿ$>ÿÿ    ∂    ÿÿÿÿΔxÿÿDÿÿÿÿŒ
  872. ÿÿÿÿ‚ÿÿ ÿÿ„ÿÿÿÿ‰)ÿÿÿÿUÿÿÿÿˆYÿÿÿÿ˜Zÿÿÿÿ˘`ÿÿ  ÿÿ˙jÿÿ !ÿÿ˚kÿÿ
  873. !"ÿÿ˝+    ÿÿÿÿÿÿ˛Kÿÿ+
  874. ÿÿÿÿˇd    ÿÿÿÿÿÿıfÿÿdÿÿÿÿƒ◊    ÿÿ5ÿÿÿÿ Qÿÿ#ÿÿ¡ÿÿ◊G=ÿÿÿÿ<¢     ÿÿÿÿ£    
  875. ÿÿÿÿ€    ÿÿ#ÿÿÿÿ(¥ÿÿ$ÿÿ    œ    ÿÿÿÿA§    ÿÿ$ÿÿÿÿ0¨    *ÿÿÿÿ[©ÿÿ%ÿÿZª     *ÿÿÿÿ«"    /ÿÿÿÿ¬&    ÿÿ2ÿÿÿÿ–*    ÿÿ3ÿÿÿÿ®-    ÿÿ4ÿÿÿÿ¯3    6ÿÿÿÿ°4ÿÿ 8ÿÿÿÿ±6ÿÿ 8ÿÿÿÿ”8ÿÿ9ÿÿÿÿ“9ÿÿ9ÿÿÿÿ´;ÿÿ "8ÿÿÿÿµ=ÿÿ %8ÿÿÿÿ¶@ÿÿ ;8ÿÿÿÿ·Aÿÿ <8ÿÿÿÿ¸Dÿÿ =8ÿÿÿÿ’Eÿÿ ?8ÿÿÿÿºFÿÿ@:ÿÿÿÿ»HAÿÿÿÿπJBÿÿÿÿ
  876. ∏Oÿÿ;ÿÿÿÿ≤Sÿÿ<<ÿÿÿÿ¿WÿÿC<ÿÿÿÿÀ^ÿÿ?<ÿÿÿÿÁaÿÿ<ÿÿÿÿÂeÿÿ<;ÿÿÿÿÃhÿÿEÿÿÿÿÄoÿÿFÿÿÿÿÅqÿÿ?;ÿÿÿÿ
  877. Ærÿÿ H<ÿÿÿÿÇsÿÿ <ÿÿÿÿÈuÿÿ&ÿÿ    ÉwuIÿÿÿÿÊzÿÿ"J<ÿÿÿÿË|ÿÿ"F<ÿÿÿÿÌÉÿÿ K<ÿÿÉÍÊu IÿÿÿÿÎÌÿÿ L<ÿÿÿÿÏÍuÿÿÿÿ‹Îÿÿ&M>ÿÿÿÿÑÏÿÿ&>ÿÿÿÿÒ‹ÿÿ&<>ÿÿÍÓÑu&IÿÿÿÿÔÒÿÿ*<?ÿÿÿÿÕÓÿÿ*C?ÿÿÿÿÖÔÿÿN<ÿÿÿÿ◊Õÿÿ"E<ÿÿÿÿØÖÿÿ*N?ÿÿÿÿÙØÿÿ"O<ÿÿÿÿÚÙÿÿ P<ÿÿœÛÚÿÿÿÿÿÿÜÛÿÿ"<ÿÿÿÿ†Üÿÿ"Q<ÿÿÿÿfi†ÿÿ-@ÿÿÿÿßfiÿÿ 8ÿÿÿÿàßÿÿ3Q8ÿÿÿÿáàÿÿ38ÿÿÓÿÿHASH‘
  878. $Ú @J˜ àù
  879. ÁN& ∏ÁN&ÂÁN&2ÅÁ¸& §Ã´◊‘KôؑYÑÛÔ!ÑÛÔ/à"ÔÎá8?Ø á´fiãã%8◊dãµÕá=è‹GØ©é?5êä ëå&
  880.     &
  881. ∂    &Û    &Ä    .»
  882. π
  883. nà &Ó &Ï
  884. &ΔJe†JkÊJeàL&    ÌL&
  885. ÁL& ≤L&ÜL&ËL&¿L&0ÀL(
  886. ßL( ·L(áL(°L(¶L(0’M'ÖM¸M´M±M µMn◊M&    ÎM& ÚM&ÙM1
  887. ¡N&ÇN&
  888. ÆN&ÔN&!ÕN&'ÑN&)ÒO)ØP&(‹T&«T&
  889. ¨V&ªd(“e”¯, ıµ&ƒ¶& –Æ&'¬2 ˛,ˇx2˝,∫QΩT&¯T&
  890. ¢m&
  891. £v√˝≈À…,nQovp˝qÀrås
  892. t/uTvywıxÃy,8{QI|v4}˝5~À5å5•    
  893. 5™    /5≠    T5∞    y5≥#&'()*.0OGPHCUø+ ,    05    16    27    38CbJUKV    (1
  894. G-    5%y·;y˝9Ù?:Ù    H<ùù$ùB3ù    $2ù    34‡J>‡>‡ ELÿ>Z0ï"f-C.D/E0FFI`A/Q0R1S2T0XJW&B.J
  895. "?
  896. #@
  897. $[
  898. %\ijgh*k…”lûHc‡/P‡9`‡:a‡1]‡7^‡8_‡DOfl0e'NA& ‘A
  899. 7ŸAL&ºAQ& €H∞¶·˘L: QUNùˆYˆÏfiZ≥Ï®f+ ⁄fx&
  900. f¸egzh“çmh’ÑÚiCodÈj–◊alq”º n°çt„nØ¥¸˚q’it‚r§élr”◊ar’Üt¥s§é˜Œt“◊Å∑yœ◊◊‰z«áoz¶ÕÄ{«á∂˙}Bod}©ÓÖm~Rÿÿ
  901. CHARÁô$ÿÿÿÿ ÿÿ ÿÿÿú    ÿÿÿfl ÿÿ ÿÿÿû
  902. ÿÿ•ÿÿ ÿóàÿÿÿúÿÿ
  903. ÿòÓ'ÿØ
  904. ÿÿ
  905. ÿòàÿÿÿ÷ àÿÿÿÿ
  906. ÿÿ"
  907. ÿÿRÿÿ ÿÿÿÿ (
  908. '
  909. ÿÿ%
  910. ÿÿÿfl
  911. ÿÿ
  912. ÿÿ     ÿÿÿÿ
  913. ÿÿÿéÿÿ"ÿ† ÿÿÿú
  914. ÿÿÿÿÿÿ
  915. ÿò
  916. àÿè    ÿÿ ÿÿàÿÿ.÷Ñ"    àÿÿàÿÿ ÿÿàÿÿ ÿÿÿÿ"    àÿÿÿÿ•à
  917.     ÿÿ
  918.     ÿÿ
  919.     ÿÿ.    ÿÿ
  920.     ÿÿ
  921. *
  922. 
  923.     )/    ÿÿ*
  924. 2
  925. ./
  926. ÿÿ        1        
  927. ÿÿ4ÿÿ&    ÿÿ&ÿÿ  ÿÿ&
  928. 6&    ÿÿÿÿ ÿÿÿÿ
  929. ÿÿ ÿÿ
  930. àÿÿ ÿÿÿÿ&ÿÿ
  931. ÿÿ
  932. ÿÿ ÿó     ÿÿàÿÿÿÿ
  933. ÿÿÿÿ ÿÿ^ÿÿòÿÿÿÿÿÿ ÿó
  934. ÿÿÿÿÿÿÿû    ÿÿ_ÿÿàÿÿÿÿ
  935. ÿÿÿÿ
  936. ÿÿÿÿÿÿÿÿ
  937. àÿÿÿÿ    ÿÿÿÿ    ÿÿ[ÿÿ à…?ÿÿHASH
  938. 5091:47E8≥"33:-;0D/&)'*+    ,    )2    *(     
  939. #à à
  940. !à* àfQàlJè8$    
  941. K
  942. 
  943. <@F; C1?b>    A     GÓ    à    àBà=à"à à(Ná¡%òoE
  944. L
  945. POI     H M
  946.     DRC?
  947. CELLÁô`πÿÿÿÿÿeÿÿÿ"ÿÿÿÿü
  948. ÿÿÿÿø
  949. ÿÿøÿÿÿÿÿÿÿÿÿÿ    ÿÿü
  950. ÿÿü
  951. ÿÿø
  952. ÿÿø
  953. ÿÿü
  954. ÿÿÿÿü
  955. ÿÿü
  956. ÿÿøÿÿøøÿÿÿÿÿÿÿÿx≥
  957. ÿÿØ$ ÿÿx• ÿÿØ 
  958. ÿÿÿÿÿÿÿÿÿÿ    ÿÿø
  959. ÿÿø ÿÿ ÿÿ
  960. ÿÿÿÿøÿÿÿÿûÿÿøÿÿøÿÿÿÿÿÿÿÿ    ÿÿÿÿøÿÿÿ ÿÿÿ
  961. ÿÿü
  962. ÿÿü ÿÿøÿÿøÿÿø    ÿÿÿÿø ÿÿø
  963. ÿÿ@ÿÿÿÿø
  964. ÿÿÿÿÿÿø ÿÿ(Ó
  965. ÿÿ√s Δ@ÿÿHASHÿ    
  966.       
  967. $ %
  968. 67(xŸx∂Ø1Ø3øøø    ø
  969. ø
  970. )ü ü >     
  971. ! " #&'
  972. ./01
  973. 45;*2*èA…‘Bú=ú
  974. -ú,ú<ú3ú8ú9ú:‡    + Æÿÿ
  975. GRPHÁôèºÿÿÿÿÿeÿÿÿBÿÿÎÿÿ
  976. ÿÿÎÿÿ
  977. ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿÿ|ÿÿHASH
  978.     Ò
  979. Î   ≠Aÿÿl
  980. RULRÁô›Æÿÿÿÿÿ#ÿÿÿ‡@ÿÿ\ÿÿ $ÿÿÿ@ÿÿ $ÿÿ     $ÿÿÿCÿÿÿÿÿÂB ÿÿ$ÿÿHÿÿ    ÿCÿÿlÿÿΔÿÿÿbBÿÿ´ÿÿØÿÿÿÂBdÿÿÿ@Cÿÿüÿÿi÷ÂB ÿÿ ÿÿDÿÿÿÿÿ    hÿÿi÷bBÿÿ
  981. ‘ÿÿ °ÿÿÿÿ$ÿÿHÿÿlÿÿΔÿÿ´ÿÿjÿÀCÿÿØÿÿüÿÿ ÿÿDÿÿ    hÿÿÿCÿÿÿÿ$ÿÿHÿÿlÿÿ÷CÿÿΔÿÿ´ÿÿxÿCÿÿhÿCÿÿîÿÀÿîC$.°•.‰°‚Iºß›™¥â䜉°¥”\¥”l¥Ì√¥Ì˛¥µì¥Ì˘ÿÿh÷Bÿÿ÷CÿÿiÿÂBdÿÿ ÿCÿÿÿCÿÿÿ@CÿÿÿÀCÿÿÿCÿÿÿBÿÿÿCÿÿÿCÿÿÿÀÿîC$.°•.‰°‚Iºß›™¥â䜉°¥”\¥”l¥Ì√¥Ì˛¥µì¥Ì˘ˆAÿÿHASHÀE;À¯$ÿÿCÿ<Cÿ8D=E?E>K÷/Kÿ*[ÿ9œ¬ù5–3∏2
  982. ùo
  983. ùÿ+K÷6Kÿdÿ
  984. ,,0Q-v.˝0À10    , Q v˝Àå
  985. /TyıÃ,Q v!˝"À#å%    
  986. &    /'    T(    y)
  987. 0@ÿ@‡@Cÿ:@KÿXŸqÄ@Y{qÄ4eeo7.á-LKUP     ¢ Œ‚
  988. £€¥„œ∂§¨©—ª«
  989. ¬‰–˝®‘Ÿ¯°±”“´ µ!"¶·#$¸’º%»&π˛'()∏* +≤,-¿.ˆ˜/01À2˘Á34ˇÂı5Ã6˙˚789Ä:ÅÆÇ;È<ÉΔ=Ê>Ë?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~•™≠∞≥∑∫Ω√≈…ÌÍ⁄ÎÏ‹ÑÒÓÔÕÖ◊؃ÙÚÛ܆fißàáâãäåæçèéêëìíîï›ñòóôõö÷øùúûü‡flÿ    
  990.   
  991. ÿÿ¡‘'ÿÿ$NAMEDefault
  992. Default SSHeaderBodyFooterFootnoteFootnote Index
  993. HeadingH2.H2 Code.CV Heading1.H1Italic HeadingH3.H3Bullet    ChecklistNumberClassic> Blue Gray 1[ Blue Gray 2yColorful≈
  994. 3D Table 1˜
  995. 3D Table 2¢
  996. Accounting«Harvard¸LegalÃDiamond
  997. Bullet+TitleAuthor)AddressU AffiliationY Bullet itemsZ Further Ref`AcknowledgmentsjFooter kFurther ReferenceQ
  998. guideWorksTitles
  999. Code styleuCode0DFNTM    HelveticaGenevaTimesPalatinoCourier:H
  1000. Letter Gothicÿÿ
  1001. Zapf DingbatsNew YorkETBL@FNTMˆ)CUTSˆ1DSUMˆ9HDNIˆrSTYLˆ|ETBLìôÿfl‡üûúùø›ñòóôõö÷
  1002.